﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using LastoRevival.Service.Contracts.Models;
using mdryden.Core.Data.Sql;

namespace LastoRevival.Service.Implementations.Data.Sql
{
	class GetUserByNameCommand : StoredProcedureCommand
	{

		public GetUserByNameCommand(string name)
			: base("Forum_GetUserByName")
		{
			AddParameter("@uname", name);
		}

	}

	class GetUserByLoginToken : StoredProcedureCommand
	{
		public GetUserByLoginToken(Guid loginToken)
			: base("Forum_GetUserByLoginToken")
		{
			AddParameter("@loginToken", loginToken);
		}
	}

	class GetMessagesOnForumPageCommand : StoredProcedureCommand
	{
		public GetMessagesOnForumPageCommand(int forumID, int page, int recsPerPage)
			: base("Forum_GetMessagesOnForumPage")
		{
			AddParameter("@forumID", forumID);
			AddParameter("@page", page);
			AddParameter("@recsPerPage", recsPerPage);
		}
	}

	class GetMessagesInThreadCommand : StoredProcedureCommand
	{
		public GetMessagesInThreadCommand(int threadID)
			: base("Forum_GetMessagesInThread")
		{
			AddParameter("@threadID", threadID);
		}
	}
	
	class GetAllForumsCommand : StoredProcedureCommand
	{
		public GetAllForumsCommand()
			: base("Forum_GetForums")
		{

		}
	}

	class GetVisibleForumsCommand : StoredProcedureCommand
	{
		public GetVisibleForumsCommand(int groupID)
			: base("Forum_GetForumsVisibleToGroup")
		{
			AddParameter("GroupID", groupID);
		}
	}

	class GetForumByIDCommand : StoredProcedureCommand
	{
		public GetForumByIDCommand(int forumID)
			: base("Forum_GetForumByID")
		{
			AddParameter("@id", forumID);
		}
	}

	class GetPostCommand : StoredProcedureCommand
	{
		public GetPostCommand(int postID, bool updateViewCount)
			: base("Forum_GetPost")
		{
			AddParameter("@id", postID);
			AddParameter("@updateViewCount", updateViewCount);
		}
	}

	class InsertPostCommand : StoredProcedureCommand
	{
		public InsertPostCommand(int userID, CreatePostModel post)
			: base("Forum_InsertPost")
		{
			// a few sanity checks (let validation hand the input, this is just so we don't put bad data
			// into the DB
			Assert(post.ForumID > 0, "Forum ID is missing");
			Assert(userID > 0, "User ID is missing");

			AddParameter("@forumid", post.ForumID);
			AddParameter("@subject", post.Subject);
			AddParameter("@thread_parent", 0);
			AddParameter("@thread_id", 0);
			AddParameter("@ip", post.IP);
			AddParameter("@client", post.Client);
			AddParameter("@body", string.Format("{0}", post.Body)); // turn nulls into an empty string
			AddParameter("@userid", userID);
		}
	}

	class InsertReplyCommand : StoredProcedureCommand
	{
		public InsertReplyCommand(int userID, CreateReplyModel reply)
			: base("Forum_InsertPost")
		{
			// a few sanity checks (let validation hand the input, this is just so we don't put bad data
			// into the DB
			Assert(reply.ForumID > 0, "Forum ID is missing");
			Assert(userID > 0, "User ID is missing");

			AddParameter("@forumid", reply.ForumID);
			AddParameter("@subject", reply.Subject);
			AddParameter("@thread_parent", reply.ParentPostID);
			AddParameter("@thread_id", reply.ThreadID);
			AddParameter("@ip", reply.IP);
			AddParameter("@client", reply.Client);
			AddParameter("@body", string.Format("{0}", reply.Body)); // turn nulls into an empty string
			AddParameter("@userid", userID);
		}
	}

	class InsertUserCommand : StoredProcedureCommand
	{
		public InsertUserCommand(CreateUserModel user, string verifyCode, DateTime verifyExpire, int groupID)
			: base("Forum_InsertUser")
		{
			AddParameter("@username", user.UserName);
			AddParameter("@userpassword", user.Password);
			AddParameter("@useremail", user.Email);

			AddParameter("@groupid", groupID);
			AddParameter("@verifycode", verifyCode);
			AddParameter("@verifyexpire", verifyExpire);
			AddParameter("@hideemail", true); 
			AddParameter("@signature", string.Empty);
			AddParameter("@signatureimageurl", string.Empty);
		}
	}

	class InsertSessionCommand : StoredProcedureCommand
	{

		public InsertSessionCommand(string username, DateTime expirationDate)
			: base("Forum_InsertSession")
		{
			AddParameter("@username", username);
			AddParameter("@expirationDate", expirationDate);
		}

	}

	class DeleteSessionCommand : StoredProcedureCommand
	{
		public DeleteSessionCommand(Guid token)
			: base("Forum_DeleteSession")
		{
			AddParameter("@LoginToken", token);
		}
	}

	class UpdateSessionCommand : StoredProcedureCommand
	{
		public UpdateSessionCommand(Guid loginToken, DateTime expirationDate)
			: base("Forum_UpdateSession")
		{
			AddParameter("@logintoken", loginToken);
			AddParameter("@expirationdate", expirationDate);
		}
	}

	class UpdatePostCommand : TextCommand
	{
		private const string text = "UPDATE Forum_Messages SET Subject=@Subject, Body=@Body, LastEdit=@LastEdit, LastEdit_UserID=@LastEditUserID WHERE ID=@PostID";

		public UpdatePostCommand(EditPostModel post, DateTime lastEdit, int lastEditUserID)
			: base(text)
		{
			AddParameter("@Subject", post.Subject);
			AddParameter("@Body", string.Format("{0}", post.Body)); // turn nulls into an empty string
			AddParameter("@PostID", post.PostID);
			AddParameter("@LastEdit", lastEdit);
			AddParameter("@LastEditUserID", lastEditUserID);
		}
	}

	class GetForumAccessForGroupCommand : TextCommand
	{
		private const string text = "SELECT ForumID, AccessType FROM Forum_GroupAccess WHERE GroupID=@groupid";

		public GetForumAccessForGroupCommand(int groupID)
			: base(text)
		{
			AddParameter("@groupid", groupID);
		}
	}

	class UpdatePostLockStateCommand : TextCommand
	{
		private const string text = "UPDATE Forum_Messages SET Locked=@locked WHERE Id=@id";

		public UpdatePostLockStateCommand(int postID, bool locked)
			: base(text)
		{
			AddParameter("@id", postID);
			AddParameter("@locked", locked);
		}
	}

	class GetUserStatsCommand : StoredProcedureCommand
	{
		public GetUserStatsCommand(int userID)
			: base("Forum_GetUserStats")
		{
			AddParameter("@userID", userID);
		}
	}

	class GetSessionExpirationCommand : StoredProcedureCommand
	{

		public GetSessionExpirationCommand(Guid loginToken)
			: base("Forum_GetSessionExpiration")
		{
			AddParameter("@loginToken", loginToken);
		}
	}

	class UpdateProfileCommand : TextCommand
	{
		private const string text = @"UPDATE Forum_Users SET 
														useremail=@email, 
														signature=@signature
													WHERE UserID=@userid";

		public UpdateProfileCommand(EditProfileModel user)
			: base(text)
		{
			AddParameter("@email", user.Email);
			AddParameter("@userid", user.UserID);
			AddParameter("@signature", string.Format("{0}", user.Signature));
		}								

	}

	class GetUsernameCommand : TextCommand
	{
		private const string text = "SELECT Username FROM Forum_Users WHERE userid=@userid";

		public GetUsernameCommand(int userID)
			: base(text)
		{
			AddParameter("@userid", userID);	
		}
	}

	class GetGroupAccessToForumCommand : TextCommand
	{
		private const string text = @"
							SELECT 
								g.groupid,
								g.groupname,
								ga.accesstype
							FROM 
								Forum_Groups g
							LEFT JOIN 
								Forum_GroupAccess ga ON g.GroupID = ga.GroupID AND ga.ForumID = @forumID";

		public GetGroupAccessToForumCommand(int forumID)
			: base(text)
		{
			AddParameter("@forumID", forumID);
		}
	}

	class UpdateGroupPermissionsForForumCommand : TextCommand
	{
		private const string text = @"
						DELETE FROM Forum_GroupAccess WHERE ForumID = @forumID AND GroupID = @groupID;

						INSERT INTO Forum_GroupAccess (ForumID, GroupID, AccessType) VALUES (@forumID, @groupID, @accessType)";

		public UpdateGroupPermissionsForForumCommand(UpdateGroupPermissionsModel access)
			: base(text)
		{
			AddParameter("@forumID", access.ForumID);
			AddParameter("@groupID", access.GroupID);
			AddParameter("@accessType", (int)access.Access);
		}

	}

	class InsertForumCommand : StoredProcedureCommand
	{
		public InsertForumCommand(CreateForumModel forum)
			: base("Forum_InsertForum")
		{
			AddParameter("@title", forum.Title);
			AddParameter("@description", string.Format("{0}", forum.Description));
			AddParameter("@indexOrder", forum.IndexOrder);
		}
	}

	class DeleteForumCommand : StoredProcedureCommand
	{

		public DeleteForumCommand(int forumID)
			: base("Forum_DeleteForum")
		{
			AddParameter("@forumID", forumID);
		}
	}

	class UpdateForumCommand : TextCommand
	{
		private const string text = "UPDATE Forum_Forums SET Title=@title, Description=@description, IndexOrder=@indexorder WHERE ForumID=@forumid";

		public UpdateForumCommand(EditForumModel forum)
			: base(text)
		{
			AddParameter("@title", forum.Title);
			AddParameter("@description", forum.Description);
			AddParameter("@indexorder", forum.IndexOrder);
			AddParameter("@forumid", forum.ForumID);
		}
	}

	class VerifyUserCommand : TextCommand
	{
		private const string CommandText = "UPDATE Forum_Users SET Verified=1 WHERE Username=@Username";

		public VerifyUserCommand(string username)
			: base(CommandText)
		{
			AddParameter("@Username", username);
		}
	}

	class GetVerificationStateCommand : TextCommand
	{
		private const string CommandText = "SELECT VerifyCode, VerifyExpire FROM Forum_Users WHERE Username=@Username";

		public GetVerificationStateCommand(string username)
			: base(CommandText)
		{
			AddParameter("@Username", username);
		}
	}

	class DeleteUserByNameCommand : TextCommand
	{
		private const string CommandText = "DELETE FROM Forum_Users WHERE Username=@Username";

		public DeleteUserByNameCommand(string username)
			: base(CommandText)
		{
			AddParameter("@Username", username);
		}
	}

	class GetOnlineUsersCommand : TextCommand
	{
		private const string CommandText =
			"SELECT DISTINCT " + // distinct because some users might have two sessions active
				"u.Username, " +
				"g.GroupName, " +
				"g.NameColor as GroupColor " +
			"FROM Forum_Sessions s " +
				"LEFT JOIN Forum_Users u ON u.UserID = s.UserID " +
				"LEFT JOIN Forum_Groups g ON g.GroupId = u.GroupId " +
			"WHERE LastActive > @Threshold";

		public GetOnlineUsersCommand(DateTime activeThreshold)
			: base(CommandText)
		{
			AddParameter("@Threshold", activeThreshold);
		}
	}
}
